#ifndef __DEMO_BASE_H__
#define __DEMO_BASE_H__

class framework
{
	typedef void (*func_update)();
	typedef void (*func_render)();
	typedef LRESULT (CALLBACK *func_msg_proc)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

private:
	IDirect3D9 *m_d3d;
	IDirect3DDevice9 *m_device;
	HWND m_wnd;
	const char* m_title;

	enum
	{
		MAX_FRAME_RATE = 120,
	};

	unsigned long m_frame_rate;
	unsigned long m_logic_count;
	unsigned long m_display_count;
	float m_flush_time;
	Timer *m_timer;

	func_update m_update;
	func_render m_render;
	func_msg_proc m_msg_proc;

public:

	bool init(HINSTANCE instance, const char *title, int width, int height, D3DDEVTYPE device_type = D3DDEVTYPE_HAL);
	void set_frame_rate(unsigned long frame_rate);
	void release();
	void main_loop();
	void register_update(func_update update);
	void register_render(func_render render);
	void register_msg_proc(func_msg_proc msg_proc);
	IDirect3DDevice9* get_device();
	static framework& get_instance();

private:

	framework() : m_d3d(NULL), m_device(NULL),
		m_wnd(0), m_title(NULL), m_frame_rate(30),
		m_logic_count(0), m_display_count(0), m_flush_time(0.0f),
		m_timer(NULL), m_render(NULL), m_msg_proc(NULL) {}

	framework& operator = (const framework& other) {}

	bool init_wnd(HINSTANCE instance, const char *title, int width, int height);
	bool init_d3d(D3DDEVTYPE device_type);

	void cleanup();
	void do_frame();
	void logic();
	void display();
	
};

#endif //__DEMO_BASE_H__

